// configmapModel.go
package models

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"myk8s/common"
	"strings"

	"github.com/tidwall/gjson"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	yamlutil "k8s.io/apimachinery/pkg/util/yaml"
	"sigs.k8s.io/yaml"
)

type Configmap struct {
	ConfigmapName string `json:"configmapName"`
	NameSpace     string `json:"nameSpace"`
	Labels        string `json:"labels"`
	CreateTime    string `json:"createTime"`
	Data          []Cmkv `json:"data"`
}

type Cmkv struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

func CmList(kubeconfig, namespace, configmapName string, labelsKey, labelsValue string) ([]Configmap, error) {
	clientset := common.ClientSet(kubeconfig)
	if namespace == "" {
		//namespace = corev1.NamespaceDefault
		namespace = corev1.NamespaceAll
	}

	//设置ListOptions
	var listOptions = metav1.ListOptions{}
	if labelsKey != "" && labelsValue != "" {
		listOptions = metav1.ListOptions{
			LabelSelector: fmt.Sprintf("%s=%s", labelsKey, labelsValue),
		}
	}

	cmList, err := clientset.CoreV1().ConfigMaps(namespace).List(context.TODO(), listOptions)
	if err != nil {
		log.Printf("list deployment error, err:%v\n", err)
	}

	var bbb = make([]Configmap, 0)
	for _, cm := range cmList.Items {
		//搜索
		if configmapName != "" {
			if !strings.Contains(cm.Name, configmapName) {
				continue
			}
		}
		var labelsStr string
		for kk, vv := range cm.ObjectMeta.Labels {
			labelsStr += fmt.Sprintf("%s:%s,", kk, vv)
		}
		if len(labelsStr) > 0 {
			labelsStr = labelsStr[0 : len(labelsStr)-1]
		}
		Items := &Configmap{
			ConfigmapName: cm.Name,
			NameSpace:     cm.Namespace,
			Labels:        labelsStr,
			CreateTime:    cm.CreationTimestamp.Format("2006-01-02 15:04:05"),
		}
		bbb = append(bbb, *Items)
	}
	return bbb, err
}

func CmCreate(kubeconfig string, bodys []byte) error {
	gp := gjson.ParseBytes(bodys)
	clusterId := gp.Get("clusterId").String()
	if kubeconfig == "" {
		kubeconfig = clusterId
	}
	configmapName := gp.Get("configmapName").String()
	nameSpace := gp.Get("nameSpace").String()

	var labelsMap = make(map[string]string)
	labelsMap["app"] = configmapName
	for _, vv := range gp.Get("lables").Array() {
		labelsMap[vv.Get("key").Str] = vv.Get("value").Str
	}

	var dataMap = make(map[string]string)
	for _, vv := range gp.Get("configmaps").Array() {
		dataMap[vv.Get("key").Str] = vv.Get("value").Str
	}

	cm := &corev1.ConfigMap{
		ObjectMeta: metav1.ObjectMeta{
			Name:      configmapName,
			Namespace: nameSpace,
			Labels:    labelsMap,
		},
		Data: dataMap,
	}

	clientset := common.ClientSet(kubeconfig)
	_, err := clientset.CoreV1().ConfigMaps(nameSpace).Create(context.TODO(), cm, metav1.CreateOptions{})
	if err != nil {
		return err
	}
	return nil
}

func CmYamlModify(kubeconfig string, yamlData []byte) error {
	data, err := yamlutil.ToJSON(yamlData)
	if err != nil {
		return err
	}
	configmap := &corev1.ConfigMap{}
	err = json.Unmarshal(data, configmap)
	if err != nil {
		return err
	}

	namespace := configmap.ObjectMeta.Namespace
	confignameName := configmap.ObjectMeta.Name
	clientset := common.ClientSet(kubeconfig)
	_, err = clientset.CoreV1().ConfigMaps(namespace).Update(context.TODO(), configmap, metav1.UpdateOptions{})
	if err != nil {
		return err
	}
	fmt.Println(namespace, confignameName)
	return err
}

func GetCmYaml(kubeconfig, namespace, configmapName string) (string, error) {
	cmClient := common.ClientSet(kubeconfig).CoreV1().ConfigMaps(namespace)
	configmap, err := cmClient.Get(context.TODO(), configmapName, metav1.GetOptions{})
	cmUnstructured, err := runtime.DefaultUnstructuredConverter.ToUnstructured(configmap)
	if err != nil {
		return "", err
	}
	yamlBytes, err := yaml.Marshal(cmUnstructured)
	if err != nil {
		return "", err
	}
	return string(yamlBytes), nil
}
